package com.fun.demo;


import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;


public class ADHander {

    public static void main(String[] args) {
        String javaVersion = System.getProperty("java.version");
        String[] ss = javaVersion.split("_");
        int ver = Integer.parseInt(ss[1]);
        if(ver > 180){
            System.out.println("java version:" + ver);
            //jdk1.8.181  improve ldap support
            System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification","true");
        }
        connect();
    }

    private static void connect() {

        String path = "ldaps://kypro.com:636";// ldaps://kypro.com:636   ldap://kypro.com:389
        String user =  "hey@kypro.com";
        String pwd =  "Heyi@1112";

        System.out.println("path:" + path);
        System.out.println("user:" + user);
        System.out.println("pwd:" + pwd);

        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        if(path.toLowerCase().startsWith("ldaps:")){
            env.put("java.naming.ldap.factory.socket", CustomSSLSocketFactory.class.getName());
            System.out.println("AD : SSL PROTOCOL");
        }
        env.put(Context.PROVIDER_URL, path);
        env.put(Context.SECURITY_PRINCIPAL, user);
        env.put(Context.SECURITY_CREDENTIALS, pwd);



        DirContext ctx = null;
        try {
           // ctx = new InitialDirContext(env);
            ctx = new InitialLdapContext(env, null);
            System.out.println("InitialDirContext OK.");

            String searchBase = "DC=kypro,DC=com";

            String searchFilter = "(&(objectCategory=person)(objectClass=user))";

            SearchControls searchCtls = new SearchControls();

            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

            String returnedAtts[] = {"sAMAccountName", "cloudExtensionAttribute"};
            searchCtls.setReturningAttributes(returnedAtts);

            NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchCtls);

            int rows = 0;
            while (answer.hasMoreElements()) {
                if(rows == 20){
                    break;
                }
                SearchResult sr = (SearchResult) answer.next();
                System.out.println((rows + 1) + " ************************************************");
                String dn = sr.getName();
                System.out.println("dn:" + dn);

                Attributes Attrs = sr.getAttributes();
                if (Attrs != null) {
                    try {
                        for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore(); ) {
                            javax.naming.directory.Attribute Attr = (Attribute) ne.next();
                            System.out.println("AttributeID:" + Attr.getID());
                            for (NamingEnumeration e = Attr.getAll(); e.hasMore(); rows++) {
                                String val = e.next().toString();
                                System.out.println("AttributeValues:" + val);
                            }
                        }
                    } catch (NamingException e) {
                        System.err.println("Throw Exception:" + e);
                    }
                }

            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (javax.naming.CommunicationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != ctx) {
                try {
                    ctx.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }




    // 绕过SSL证书校验
    public static class CustomSSLSocketFactory extends SSLSocketFactory {
        private SSLSocketFactory socketFactory;

        public CustomSSLSocketFactory() {
            try {
                SSLContext ctx = SSLContext.getInstance("TLS");
                ctx.init(null, new TrustManager[]{new DummyTrustmanager()}, new SecureRandom());
                socketFactory = ctx.getSocketFactory();
            } catch (Exception ex) {
                ex.printStackTrace(System.err);
            }
        }

        public static SocketFactory getDefault() {
            return new CustomSSLSocketFactory();
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return socketFactory.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            return socketFactory.getSupportedCipherSuites();
        }

        @Override
        public Socket createSocket(Socket socket, String string, int num, boolean bool) throws IOException {
            return socketFactory.createSocket(socket, string, num, bool);
        }

        @Override
        public Socket createSocket(String string, int num) throws IOException, UnknownHostException {
            return socketFactory.createSocket(string, num);
        }

        @Override
        public Socket createSocket(String string, int num, InetAddress netAdd, int i) throws IOException, UnknownHostException {
            return socketFactory.createSocket(string, num, netAdd, i);
        }

        @Override
        public Socket createSocket(InetAddress netAdd, int num) throws IOException {
            return socketFactory.createSocket(netAdd, num);
        }

        @Override
        public Socket createSocket(InetAddress netAdd1, int num, InetAddress netAdd2, int i) throws IOException {
            return socketFactory.createSocket(netAdd1, num, netAdd2, i);
        }


        /**
         * 证书
         */
        public static class DummyTrustmanager implements X509TrustManager {
            public void checkClientTrusted(X509Certificate[] cert, String string) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] cert, String string) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

        }
    }


}
